package com.flycent.fanbao.net.parser;

import java.io.StringReader;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.stream.JsonReader;

/**
 * 基础解析类，只针对 JSON 解析，解析的规则为 T
 * 
 *  <p>该类是基于 Gson 实现的，在解析时需要知道泛型的类型。
 *  <p> 在使用 {@link #getGenericType(Class)} 该方法时，传入的类必须是匿名内部类，这样才可以的到泛型
 *
 * @param <T> JSON 解析后对应的类型
 *
 * @author Liu.Wenzhu  <lwz0316.gmail.com>
 * @date 2014年7月5日 下午7:05:43 
 *
 */
public class BaseResponseParser<T> implements ResponseParser<T> {

    /**
     * 该方法试用于在所有泛型已经被指定的情况，否则则需要使用 {@link #parse(String, Type)}
     * @param jsonData
     * @return
     */
    public T parse(String jsonData) {
    	return parse(jsonData, getClass());
    }
    
    /**
     * 该方法试用于待解析的类中的泛型未知的情况
     * <br>NOTE： 必须使用匿名内部类调用方法
     * <pre>
     * 	public abstract class A&lt;T ? extends B> {
     * 		....
     * 		        EHBaseResponseParser<T> parser = new EHBaseResponseParser(){};
     * 			parser.parse(responseString, EHBaseResponseParser.getGenericType(getClass()))
     *                ....
     * 	} 
     * </pre>
     * @see #parse(String)
     * 
     */
    @Override
    public T parse(String jsonData, Type type) {
	  	try {
	  		// 简单校验是否json
	  		if( TextUtils.isEmpty(jsonData) || !(jsonData.startsWith("{") || jsonData.startsWith("[")) ) {
	  			return null;
	  		}
	  		StringReader in = new StringReader(jsonData);
	  		JsonReader reader = new JsonReader(in);
	  		reader.setLenient(true);
	  		T t = new Gson().fromJson(reader, type);
	  		in.close(); 
	  		in = null;
	  		reader.close();
	  		reader = null;
	  	    return t;
	  	} catch (Exception e) {
	  	    e.printStackTrace();
	  	}
	  	return null;
    }

    /**
     * 得到 泛型的类型
     * 
     * <p>使用该方法的前提是在实例化对象时使用其的匿名内部类，这样才可以得到泛型的类型
     * 
     * @param clazz 匿名内部类
     * @return
     * @throws Exception 若没有使用匿名内部类，则调用该方法时会抛出异常
     */
    public static Type getGenericType(Class<?> clazz) throws Exception {
		return getGenericType(clazz, 0);
    }
    
    /**
     * 得到 泛型的类型
     * 
     * <p>使用该方法的前提是在实例化对象时使用其的匿名内部类，这样才可以得到泛型的类型
     * 
     * @param clazz 匿名内部类
     * @param index 第几个泛型, 下标从 0 开始
     * @return
     * @throws Exception 若没有使用匿名内部类，则调用该方法时会抛出异常
     */
    public static Type getGenericType(Class<?> clazz, int index) throws Exception {
		Type mySuperClass = clazz.getGenericSuperclass();
		try {
		    Type type = ((ParameterizedType) mySuperClass) .getActualTypeArguments()[index];
		    return type;
		} catch (ClassCastException e) {
		    throw new Exception(
			    "please use AnonymousInner Class to get generic Type");
		}
    }

}
